package orm

import (
	"database/sql"
)

// 数据库操作对象，对应*sqlx.DB
type DataBaseOperator interface {
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	Exec(query string, args ...interface{}) (sql.Result, error)
	NamedExec(query string, arg interface{}) (sql.Result, error)
	Get(dest interface{}, query string, args ...interface{}) error
	Select(dest interface{}, query string, args ...interface{}) error
}

// 获取字段信息的临时需要的方法
// 可以手动实现，也可以用反射获取
type TableFieldInfoProvider interface {
	Fields() []string
	ColumnName(f string) string
	GetFieldValue(f string) interface{}
	SetFieldValue(f string, v interface{})
}

type SetFieldInfoProvider interface {
	Fields() []string
	// 字段对应的列的信息
	// table，表名。只有一个表时table可省略，否则要返回表的原名或别名
	// column，列原名。在不需要列别名的情况下可省略
	// name，列名。可返回列的原名或别名
	Column(f string) (name, table, column string)
	GetFieldValue(f string) interface{}
	SetFieldValue(f string, v interface{})
}

// 数据表对应的结构体的接口
type TableDefiner interface {
	TableName() string
}

// 自增id作为主键的表
type SimpleTableDefiner interface {
	TableDefiner
	PrimaryKey() string
}

// 一个例子，也可以直接嵌入到结构体中
type BaseSimpleTable struct {
	ID int `json:"id" db:"id"`
	Agent
}

func (BaseSimpleTable) TableName() string {
	return ""
}

func (BaseSimpleTable) PrimaryKey() string {
	return "ID"
}

// 给数据集的查询追加条件的方式
type CondAppendMode int

const(
	Empty CondAppendMode = iota // 查询中已经有where/having了，继续追加
	Where // 正常的查询条件
	Having // 查询是聚合
)

// 定义数据集的接口
type SetDefiner interface {
	QueryBody() string
	CondAppendMode() CondAppendMode
}

// 包含表达式列的表的接口
type ExprColumnDefiner interface {
	Expr(f string) string
}